package com.surge;

import java.sql.Connection;
import java.sql.SQLException;
import java.util.Iterator;
import java.util.List;

import org.hibernate.Criteria;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.boot.MetadataSources;
import org.hibernate.boot.registry.StandardServiceRegistry;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.jdbc.Work;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;


@SuppressWarnings({ "rawtypes", "deprecation", "unchecked" })
public class SurgeTest {

	private SessionFactory sessionFactory;
	// 生产环境不允许 把session与transaction 设置成成员变量，因为涉及到并发问题
	private Session session;
	private Transaction transaction;

	// junit 方法init 与 destory。 这样只需要test中写主要的业务测试逻辑
	@Before
	public void init() {
		// 1、 版本5.x
		final StandardServiceRegistry registry = new StandardServiceRegistryBuilder().configure() // configures
																									// settings
																									// from
																									// hibernate.cfg.xml
				.build();
		try {
			sessionFactory = new MetadataSources(registry).buildMetadata().buildSessionFactory();
		} catch (Exception e) {
			System.out.println(e);
			StandardServiceRegistryBuilder.destroy(registry);
		}
		// 2. 创建一个 Session 对象
		session = sessionFactory.openSession();

		// 3. 开启事务
		transaction = session.beginTransaction();
	}

	@After
	public void destory() {
		// 5. 提交事务
		transaction.commit();

		// 6. 关闭 Session
		session.close();

		// 7. 关闭 SessionFactory 对象
		sessionFactory.close();
	}

	/*
	 * ============================ 测试逻辑代码 ============================
	 */

	/*
	 * 二级缓存
	 */
	@Test
	public void testHibernateSecondLevelCache(){
		
		Employee employee = (Employee) session.get(Employee.class, 1);
		System.out.println(employee.getName()); 
		
		transaction.commit();  //  提交事务，关闭session  一级缓存（session级别）失效
		session.close();
		
		session = sessionFactory.openSession(); // 开新的session
		transaction = session.beginTransaction();
		// 配置二级缓存
		Employee employee2 = (Employee) session.get(Employee.class, 1); // 从缓存中获取。只发送了一条查询语句
		System.out.println(employee2.getName()); 
//		<class-cache usage="read-only" class="com.surge.Employee"/>
		
	}
	
	
	@Test
	public void testCollectionSecondLevelCache(){
		Department dept = (Department) session.get(Department.class, 80);
		System.out.println(dept.getName());
		System.out.println(dept.getEmps().size()); 
		
		transaction.commit();
		session.close();
		
		session = sessionFactory.openSession();
		transaction = session.beginTransaction();
		
		Department dept2 = (Department) session.get(Department.class, 80);
		System.out.println(dept2.getName());
		System.out.println(dept2.getEmps().size()); 
	}
	
	/**
	 * 查询缓存
	 */
	@Test
	public void testQueryCache(){
		Query query = session.createQuery("FROM Employee");
		query.setCacheable(true);  // 配置查询缓存
		
		List<Employee> emps = query.list();
		System.out.println(emps.size());
		
		emps = query.list();
		System.out.println(emps.size());
		
		Criteria criteria = session.createCriteria(Employee.class);
		criteria.setCacheable(true);  // 配置查询缓存
	}
	
	/**
	 * 时间戳缓存
	 */
	@Test
	public void testUpdateTimeStampCache(){
		Query query = session.createQuery("FROM Employee");
		query.setCacheable(true);
		
		List<Employee> emps = query.list();
		System.out.println(emps.size());
		
		Employee employee = (Employee) session.get(Employee.class, 100);
		employee.setSalary(30000); 
		
		emps = query.list();  // hibernate 通过时间戳 自动更新缓存，使用离自己最近的缓存
		System.out.println(emps.size());
	}
	
	/**
	 * 批量查询
	 */
	@Test
	public void testQueryIterate(){
		Department dept = (Department) session.get(Department.class, 70);
		System.out.println(dept.getName());
		System.out.println(dept.getEmps().size()); 
		
		
		
		Query query = session.createQuery("FROM Employee e WHERE e.dept.id = 80");
//		List<Employee> emps = query.list();
//		System.out.println(emps.size()); 
		
		// 使用Iterator，不会特别快。当字段特别多的时候，可以考虑使用，因为他的查询语句只查id。
		Iterator<Employee> empIt = query.iterate();
		while(empIt.hasNext()){
			System.out.println(empIt.next().getName()); 
		}
	}
	
	
	/**
	 * 事务
	 */
	@Test
	public void testManageSession(){
		
		//获取 Session
		//开启事务
		Session session = HibernateUtils.getInstance().getSession();
		System.out.println("-->" + session.hashCode());
		Transaction transaction = session.beginTransaction();
		
		DepartmentDao departmentDao = new DepartmentDao();
		
		Department dept = new Department();
		dept.setName("ATGUIGU");
		
		departmentDao.save(dept);
		departmentDao.save(dept);
		departmentDao.save(dept);
		
		// 在配置文件配置 管理session的管理方式为 thread
		// 若 Session 是由 thread 来管理的, 则在提交或回滚事务时, 已经关闭 Session 了. 
		transaction.commit();
		
		System.out.println(session.isOpen()); 
	}
	
	
	/**
	 * 存储过程
	 */
	@Test
	public void testBatch(){
		session.doWork(new Work() {			
			public void execute(Connection connection) throws SQLException {
				//通过 JDBC 原生的 API 进行操作, 效率最高, 速度最快!
			}
		});
	}
	
	
	
	
	
	
	
}
